package org.springonrails.template;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springonrails.model.AppConfig;
import org.springonrails.template.freemarker.FreeMarkerTemplateLocator;

import freemarker.template.Configuration;
import freemarker.template.DefaultObjectWrapper;

public class BuiltInTemplateRegistry 
{
	private static Log log = LogFactory.getLog(BuiltInTemplateRegistry.class);
	public static final boolean NOT_APPLY_TO_EACH_ENTITY = false;
	public static final boolean APPLY_TO_EACH_ENTITY = true;
	
	private List<TemplateDef> templateList;
	private Configuration freeMarkerConfig;	
	private AppConfig appConfig;
	
	  
	
	
	public List<TemplateDef> getTemplateList() {
		return templateList;
	}

	public void setTemplateList(List<TemplateDef> templateList) {
		this.templateList = templateList;
	}

	public BuiltInTemplateRegistry(AppConfig appConfig)
	  {
		 freeMarkerConfig = new Configuration();
		 freeMarkerConfig.setClassForTemplateLoading(FreeMarkerTemplateLocator.class, "");
		 freeMarkerConfig.setObjectWrapper(new DefaultObjectWrapper()); 
		 this.appConfig = appConfig;
		 this.templateList = new ArrayList<TemplateDef>();
		 try{
			loadTemplates();			
		}catch (Exception e) {
			log.fatal("Failed to templates.", e);
			throw new RuntimeException("Failed to templates.", e);
		}
		 
	  }
	  
	  protected void loadTemplates() throws IOException
	  {	 
		  loadWebTemplates();
		  loadSpringConfigTemplates();
		  loadServiceTemplates();
		  loadModelTemplates();
		  loadOrmTemplates();
		  if(appConfig.isWebServiceApp() )
			{
				//We do not need view.
			}else{
				loadXmlViewsTemplates();
				
				if(appConfig.getViewType().equalsIgnoreCase("both") ||  appConfig.getViewType().equalsIgnoreCase("jstl")
						 ||  appConfig.getViewType().equalsIgnoreCase("jsp"))
				{
					loadJstlViewTemplates();
				}
				loadXmlViewsTemplates();				
				loadControllersTemplates();
			}
		  
	  }
	  
	  
	  
	  protected void loadModelTemplates() throws IOException
	  {
		  templateList.add(createTemplateDef("model/PoJo.ftl", 
					APPLY_TO_EACH_ENTITY, 
					this.appConfig.getJavaModelDirectory(), 
					null, null, ".java" 
					));	
			
			templateList.add(createTemplateDef("dao/InterfaceDAO.ftl", 
					APPLY_TO_EACH_ENTITY,  
					this.appConfig.getJavaDaoDirectory(), 
					null, "DAO", ".java" 
					));		
			
			templateList.add(createTemplateDef("dao/mock/DAOImpl.ftl", 
					APPLY_TO_EACH_ENTITY,  
					this.appConfig.getJavaDaoMockDirectory(), 
					null, "DAOImpl", ".java"));
	  }
	  
	  protected void loadXmlViewsTemplates() throws IOException
	  {
		 
		  templateList.add(createTemplateDef("view/FlexXMLView.ftl", 
				  NOT_APPLY_TO_EACH_ENTITY, 
				  this.appConfig.getJavaViewDirectory(), 
					null, "FlexXMLView", ".java"));
			
			templateList.add(createTemplateDef("view/FlexXMLViewResolver.ftl", 
					NOT_APPLY_TO_EACH_ENTITY,
					this.appConfig.getJavaViewDirectory(),
					null, "FlexXMLViewResolver", ".java" 
					));
			
		  templateList.add(createTemplateDef("xml/AbstractObjectXMLSerializer.ftl", 
					NOT_APPLY_TO_EACH_ENTITY, 
					this.appConfig.getJavaXmlDirectory(), 
					null, "AbstractObjectXMLSerializer", ".java" 
					));
			templateList.add(createTemplateDef("xml/DefaultObjectXMLSerializer.ftl", 
					NOT_APPLY_TO_EACH_ENTITY, 
					this.appConfig.getJavaXmlDirectory(),  
					null, "DefaultObjectXMLSerializer", ".java"));
			templateList.add(createTemplateDef("xml/ObjectXMLSerializer.ftl", 
					NOT_APPLY_TO_EACH_ENTITY, 
					this.appConfig.getJavaXmlDirectory(), 
					null, "ObjectXMLSerializer", ".java"));
			
			templateList.add(createTemplateDef("xml/ObjectXMLSerializerFactory.ftl", 
					NOT_APPLY_TO_EACH_ENTITY, 
					this.appConfig.getJavaXmlDirectory(), 
					null, "ObjectXMLSerializerFactory", ".java"));
			
			templateList.add(createTemplateDef("xml/ErrorXMLSerializer.ftl", 
					NOT_APPLY_TO_EACH_ENTITY, 
					this.appConfig.getJavaXmlDirectory(),  
					null, "ErrorXMLSerializer", ".java"));
			
			templateList.add(createTemplateDef("xml/SimpleBeanXMLSerializer.ftl", 
					NOT_APPLY_TO_EACH_ENTITY, 
					this.appConfig.getJavaXmlDirectory(), 
					null, "SimpleBeanXMLSerializer", ".java"));		
	
	  }
	  
	  protected void loadControllersTemplates() throws IOException
	  {
		  if(!appConfig.isMultipleController()){
				templateList.add(createTemplateDef("controller/AbstractSpringController.ftl", 
						NOT_APPLY_TO_EACH_ENTITY, 
						this.appConfig.getJavaControllerDirectory(), 
						null, "AbstractSpringController", ".java" 
						));
				
				
				templateList.add(createTemplateDef("controller/SpringController.ftl", 
						APPLY_TO_EACH_ENTITY, 
						this.appConfig.getJavaControllerDirectory(),
						"Spring", "Controller", ".java"));		
			}else{		
				templateList.add(createTemplateDef("controller/ListViewController.ftl", 
						APPLY_TO_EACH_ENTITY, 
						this.appConfig.getJavaControllerDirectory(),
						"", "ListViewController", ".java"));
				
				templateList.add(createTemplateDef("controller/DetailViewController.ftl", 
						APPLY_TO_EACH_ENTITY, 
						this.appConfig.getJavaControllerDirectory(),
						"", "DetailViewController", ".java"));
				
				templateList.add(createTemplateDef("controller/AddController.ftl", 
						APPLY_TO_EACH_ENTITY, 
						this.appConfig.getJavaControllerDirectory(), 
						"", "AddController", ".java"));
				
				templateList.add(createTemplateDef("controller/UpdateController.ftl", 
						APPLY_TO_EACH_ENTITY, 
						this.appConfig.getJavaControllerDirectory(), 
						"", "UpdateController", ".java"));
				templateList.add(createTemplateDef("controller/DeleteController.ftl", 
						APPLY_TO_EACH_ENTITY, 
						this.appConfig.getJavaControllerDirectory(), 
						"", "DeleteController", ".java"));
			}
	  }
	  
	  protected void loadServiceTemplates() throws IOException
	  {
		  
		  templateList.add(createTemplateDef("service/ServiceInterface.ftl", 
				  NOT_APPLY_TO_EACH_ENTITY,  
				  this.appConfig.getJavaTransDirectory(), 
					null, appConfig.getAppJavaName() + "Service", ".java"));
		  templateList.add(createTemplateDef("service/ServiceImpl.ftl", 
					NOT_APPLY_TO_EACH_ENTITY, 
					this.appConfig.getJavaTransDirectory(), 
					null, appConfig.getAppJavaName() + "ServiceImpl", ".java" 
					));	
		  /*
		  templateList.add(createTemplateDef("trans/TransactionProxy.ftl", 
				  NOT_APPLY_TO_EACH_ENTITY,  
				  this.appConfig.getJavaTransDirectory(), 
					null, "TransactionProxy", ".java"));
		  templateList.add(createTemplateDef("trans/TransactionProxyImpl.ftl", 
					NOT_APPLY_TO_EACH_ENTITY, 
					this.appConfig.getJavaTransDirectory(), 
					null, "TransactionProxyImpl", ".java" 
					));	
		  */
		  templateList.add(createTemplateDef("controller/ActionBean.ftl", 
				  NOT_APPLY_TO_EACH_ENTITY,  
				  this.appConfig.getJavaControllerDirectory(), 
					null, "ActionBean", ".java" 
					));
		  templateList.add(createTemplateDef("controller/ServerProcessStatus.ftl", 
				  NOT_APPLY_TO_EACH_ENTITY, 
				  this.appConfig.getJavaControllerDirectory(), 
					null, "ServerProcessStatus", ".java" 
					));			
	  
	  }
	  
	  protected void loadOrmTemplates() throws IOException
	  {
		  if(appConfig.getOrmType().equalsIgnoreCase("hibernate")){				
			//case 1: //hibernate;
				templateList.add(createTemplateDef("dao/hibernate/DAOImpl.ftl", 
						APPLY_TO_EACH_ENTITY, 
						this.appConfig.getJavaDaoHibernateDirectory(),
						null, "DAOImpl", ".java"));
				templateList.add(createTemplateDef("model/mapping/hibernate-orm-map.ftl", 
						APPLY_TO_EACH_ENTITY, 
						this.appConfig.getJavaModelMappingDirectory(),
						null, null, ".hbm.xml"));					
				
		  }else{				
			
			templateList.add(createTemplateDef("dao/ibatis/DAOImpl.ftl", 
					APPLY_TO_EACH_ENTITY, 
					this.appConfig.getJavaDaoIbatisDirectory(), 
						null, "DAOImpl", ".java" 
						));
			
			templateList.add(createTemplateDef("model/mapping/ibatis-sql-map.ftl", 
					APPLY_TO_EACH_ENTITY,
					this.appConfig.getJavaModelMappingDirectory(), 
					null, null, ".xml"
					));
			templateList.add(createTemplateDef("model/mapping/ibatis-sql-map-config.ftl", 
					NOT_APPLY_TO_EACH_ENTITY, 
					this.appConfig.getWebInfDirectory(), 
					"sql-map-config", null, ".xml" 
					));	
			
	    }
	  }
	  
	  
	  protected void loadJstlViewTemplates() throws IOException
	  {
		  templateList.add(createTemplateDef("jsp/index-jsp.ftl", 
					NOT_APPLY_TO_EACH_ENTITY, 
					this.appConfig.getWebAppDirectory(),
					"", "index", ".jsp"));		  
		  if(appConfig.isMultipleController()){	
				
				templateList.add(createTemplateDef("jsp/entity-detail-view-jsp.ftl", 
						APPLY_TO_EACH_ENTITY, 
						this.appConfig.getSpringViewJspDirectory(),
						null, "DetailView", ".jsp"));
				
				templateList.add(createTemplateDef("jsp/entity-add-view-jsp.ftl", 
						APPLY_TO_EACH_ENTITY, 
						this.appConfig.getSpringViewJspDirectory(), 
						"", "AddView", ".jsp"));
				
				templateList.add(createTemplateDef("jsp/entity-list-view-jsp.ftl", 
						APPLY_TO_EACH_ENTITY, 
						this.appConfig.getSpringViewJspDirectory(),
						"", "ListView", ".jsp"));
			}else{
				templateList.add(createTemplateDef("jsp/entity-view-jsp.ftl", 
						APPLY_TO_EACH_ENTITY, 
						this.appConfig.getSpringViewJspDirectory(),
						"", "", ".jsp"));
			}
			
			
	  }
	  
	  protected void loadWebTemplates() throws IOException
	  {
		  templateList.add(createTemplateDef("web-xml.ftl", 
				          NOT_APPLY_TO_EACH_ENTITY, 
					this.appConfig.getWebInfDirectory(),
					"web", null, ".xml"));
		 
		  templateList.add(createTemplateDef("jdbc-properties.ftl", 
				  NOT_APPLY_TO_EACH_ENTITY, 
					this.appConfig.getWebInfDirectory(), 
					"jdbc", null, ".properties"));
			
			templateList.add(createTemplateDef("log4j-properties.ftl", 
					NOT_APPLY_TO_EACH_ENTITY, 
					this.appConfig.getWebInfDirectory(),
					"log4j", null, ".properties"));		
					
			templateList.add(createTemplateDef("automate/maven-2-pom.ftl", 
					NOT_APPLY_TO_EACH_ENTITY, 
					this.appConfig.getProjectDirectory(),
					null, "pom", ".xml"	));
					
			templateList.add(createTemplateDef("DDL/EntityDDL.ftl", 
					NOT_APPLY_TO_EACH_ENTITY,  
					this.appConfig.getDDLDirectory(), 
					null, "entities", ".sql"));			  
	  }
	  
	  protected void loadSpringConfigTemplates() throws IOException
	  {
		  
		  if(!appConfig.isSpring2()){				
				templateList.add(createTemplateDef("spring-1-context.ftl", 
						NOT_APPLY_TO_EACH_ENTITY, 
						this.appConfig.getWebInfDirectory(),						
						"spring-servlet", null, ".xml" 
						));
				templateList.add(createTemplateDef("spring-1-dataAccess-context.ftl", 
						NOT_APPLY_TO_EACH_ENTITY, 
						this.appConfig.getWebInfDirectory(),						
						"dataAccessContext", null, ".xml"
						));
			}else{
				templateList.add(createTemplateDef("spring-2-context.ftl", 
						NOT_APPLY_TO_EACH_ENTITY, 
						this.appConfig.getWebInfDirectory(),	
						"spring-servlet", null, ".xml"));
				
				templateList.add(createTemplateDef("spring-2-dataAccess-context.ftl", 
						NOT_APPLY_TO_EACH_ENTITY, 
						this.appConfig.getWebInfDirectory(),	
						"dataAccessContext", null, ".xml"));
			}
	  }
	  
	 
	  
	  
	  protected BuiltInFreeMarkerTemplateDef createTemplateDef(
			  String templatePath, boolean applyToEachEntity, 
			  File outputDirectory, String prefix,
			  String suffix, String extension) throws IOException
	  {
		  if(log.isInfoEnabled()) log.info("Loading template >>> " + templatePath);
		  return new BuiltInFreeMarkerTemplateDef(applyToEachEntity,
				  outputDirectory,
				  prefix,
				  suffix,
				  extension,
				  freeMarkerConfig.getTemplate(templatePath)
				  );
	  }
	  
	
}
